<?php
namespace app\api\service;


use app\user\model\UserModel;
use think\Controller;
use think\Db;
//支付宝支付类
vendor('alipay.wappay.service.AlipayTradeService');
vendor('alipay.wappay.buildermodel.AlipayTradeWapPayContentBuilder');
vendor('alipay.wappay.buildermodel.AlipayTradeRefundContentBuilder');
vendor('alipay.wappay.buildermodel.AlipayTradeFastpayRefundQueryContentBuilder');

//微信支付类
vendor('wxpay.WxPayConfig');
vendor('wxpay.WxPayApi');
vendor('wxpay.Notify');
vendor('wxpay.JsApi');



header("Content-type: text/html; charset=utf-8");
header("Access-Control-Allow-Origin:*");
class PayService extends Controller {
    /**
     * 支付分发处理
     * @param $param 接收到的参数  主要是支付方式,和交易密码
     * @param $user  用户信息 id,balance(余额),more['is_vip'](是否是会员),more['deal'](交易密码)  如：余额支付需要进行余额过滤  微信支付需要过滤openid
     * @param $good_data
     * @param $type  商品类型 （很重要）
     *
     */
    public function checkPay($param,$user,$good_data,$type){
        $return=['code'=>0,'msg'=>'支付出错'];
        switch ($param['pay']){
            //余额支付
            case 'balance_pay':
                //检验交易密码是否正确
                if(!cmf_compare_password($param['deal'],$user['deal'])){
                    $return=['code'=>0,'msg'=>'交易密码错误'];
                    return $return;
                }
                $return=$this->balancePay($user,$good_data,$type);
                break;
            //微信支付
            case 'wechat_pay':
                $up = Db::name('order')->where('order_id',$good_data['order_id'])->update(['pay_type'=>1]);
                if($up === false){
                    $return=['code'=>0,'msg'=>'购买失败8','data'=>''];
                    return $return;
                }
                if(cmf_is_wechat()){
                    //调用微信公众号支付
                    $res=$this->wxJsPay($good_data);
                    return $res;
                }else if (cmf_is_mobile()){
                    //调用微信H5支付
                    $res=$this->wxH5Pay($good_data);
                    return $res;
                }else {
                    //生成支付二维码
                }
                break;
            //支付宝支付
            case 'ali_pay':
                $up = Db::name('order')->where('order_id',$good_data['order_id'])->update(['pay_type'=>1]);
                if($up === false){
                    $return=['code'=>0,'msg'=>'购买失败8','data'=>''];
                    return $return;
                }
                if(cmf_is_mobile()){
                    //跳转支付宝支付
                    $this->redirect('api/pay/aliPay',['order_id'=>$good_data['order_id']]);
                }else{
                    //生成支付二维码
                }
                break;
            default:
                $this->error('支付方式错误');

        }
        return $return;
    }
    /*
     * 余额支付
     * $user  用户信息
     * $good_data  商品信息
     * $type   商品类型
     *
     */
    private function balancePay($user,$good_data,$type){

        if ($user['balance'] >= $good_data['pay_money']){
            $up = Db::name('order')->where('order_id',$good_data['order_id'])->update(['pay_type'=>1]);
            if($up === false){
                $return=['code'=>0,'msg'=>'购买失败8','data'=>''];
                return $return;
            }
            $insert_user_order = $good_data;

            Db::startTrans();
            //扣除用户金额
            $userModel=new UserModel();

            $up_user_money=$userModel->where('id',$user['id'])->setDec('balance',$good_data['pay_money']);
            if($up_user_money === false){
                Db::rollback();
                //扣除失败
                $return=['code'=>0,'msg'=>'支付失败','data'=>$insert_user_order];
                return $return;
            }
            //余额记录写入
            $user_balance=[
                'user_id'       => $user['id'],
                'create_time'   => time(),
                'change'        => $good_data['pay_money'],
                'balance'       => $user['balance']-$good_data['pay_money'],
                'remark'        => '购买商品',
            ];
            Db::name('user_balance_log')->insert($user_balance);



            //改变支付状态
            $up_order_pay=$this->orderPaySuccess($insert_user_order['order_id'],['pay_time'=>time()]);
            if($up_order_pay == false){
                Db::rollback();
                //更新失败
                $return=['code'=>0,'msg'=>'支付失败','data'=>$insert_user_order];
                return $return;
            }

            //处理订单   改变发货状态
            $up_user_order=$this->orderDataDispose($insert_user_order['order_id']);
            if($up_user_order === false){
                Db::rollback();
                $return=['code'=>0,'msg'=>'购买失败2','data'=>"增加积分失败或者处理订单失败"];
                return $return;
            }
            //购买成功
            //更新用户缓存
            $new_user=$userModel->where('id',$user['id'])->find()->toArray();

            cmf_update_current_user($new_user);

            Db::commit();
            return $return=['code'=>1,'msg'=>'购买成功','data'=>''];

        }else{
            return $return=['code'=>0,'msg'=>'余额不足'];
        }
    }
    /*
     * 订单支付成功
     *  $order_id   订单id
     *  $arr        需要更新的值 可以为空
     */
    public function orderPaySuccess($order_id,$updata=[]){
        $arr=['pay_status'=>1];
        if(!empty($updata)){
            $arr=array_merge($arr,$updata);
        }
        //更新订单
        $up=Db::name('order')->where(['order_id'=>$order_id])->update($arr);
        if($up !== false){

            //更新缓存
            cache(CMS_NAME . '_order_'.$order_id,NULL);
            return true;
        }
        return false;

    }
    /*
     * 订单信息处理
     * $order_id   订单id
     *
     */
    public function orderDataDispose($order_id){
        $return=false;

        $order=$this->getOrderDataToId($order_id);

        if ($order){
            //订单已付款，未发货  未退款才进入
            if($order['pay_status'] == 1 && $order['order_status'] == 0 && $order['shipping_status'] == 0){
                //扣除库存

                //先取出订单快照
                $order_sub = Db::name('order_sub')->where('order_id',$order['order_id'])->field('goods_id,spec_path,goods_number')->select();
                $goods_sku_query = Db::name('mall_goods_sku');
                $goods_query = Db::name('mall_goods');
                $up_status = true;
                foreach ($order_sub as $s_v){
                    $goods_sku_data = $goods_sku_query->where(['goods_id'=>$s_v['goods_id'],'item_path'=>$s_v['spec_path']])->field('id')->find();
                    if(!empty($goods_sku_data)){
                        //减商品sku的库存
                        $up = $goods_sku_query->where(['goods_id'=>$s_v['goods_id'],'item_path'=>$s_v['spec_path']])->setDec('store_count',$s_v['goods_number']);
                        if(!$up){
                            $up_status = false;
                            break;
                        }
                    }else{
                        //直接减商品库存
                        $up = $goods_query->where('id',$s_v['goods_id'])->setDec('store_count',$s_v['goods_number']);
                        if(!$up){
                            $up_status = false;
                            break;
                        }
                    }
                }
                ($up_status) ? $return = true : false;

            }
        }
        return $return;
    }

    /*
     * 获取订单信息
     */
    public function getOrderDataToId($order_id){
        $data= Db::name('order')->where('order_id',$order_id)->find();
        if(is_null($data)){
            $data=false;
        }
        return $data;
    }




    /*
     * 转账到支付宝账户
     */
    public function AlipayFundTransToaccountTransferRequest($maid_id){

        $this->error('暂时无法使用');
        die;
        $arr = [
            'out_biz_no'     => $maid_data['maid_id'],
            'payee_account'  => $user_info['zfb'],
            'amount'         => number_format($maid_data['user_maid'],2),
            'payer_show_name'=> '',
            'remark'         => '',
            'payee_real_name'=> $user_info['name']
        ];


        $config = config('alipay_config');
        $alipay=new \AlipayTradeService($config);
        $res=$alipay->alipayFundTransToaccount($arr);

        $resultCode = $res->code;
        if(!empty($resultCode) && $resultCode == 10000){
            $resultInfo=[
                'code'            => $resultCode,
                'alipay_order_id' => $sub_code = $res->order_id,
            ];
            return ['code'=>200,'msg'=>$resultInfo];
        } else {
            $sub_code = $res->sub_code;
            $sub_msg  = $res->sub_msg;
            $error=[
                'code'      => $resultCode,
                'sub_code'  => $sub_code,
                'sub_msg'   => $sub_msg
            ];
            return ['code'=>0,'msg'=>$error];
        }

        //return $res;
    }
    /*
     *  微信公众号支付
     */
    private function wxJsPay($order_data){

        $body               =   $order_data['goods_name'];           //商品描述
        $out_trade_no       =   $order_data['order_id'];           //订单ID
        $total_fee          =   $order_data['pay_money'];          //价格
        $spbill_create_ip   =   get_client_ip(0,true);   //客户端ip
        $openid             =   session('openid');     //openid
        if(is_null($openid)){
            $return=[
                'code' => 0,
                'msg'  => '支付出错',
            ];
            return $return;
        }

        $input=new \WxPayUnifiedOrder();
        $input->SetBody($body);
        $input->SetOut_trade_no($out_trade_no);
        $input->SetTotal_fee($total_fee*100);
        $input->SetSpbill_create_ip($spbill_create_ip);
        $url = get_http_type() . $_SERVER['HTTP_HOST'] ;
        $input->SetNotify_url($url .'/api/pay/wxNotifyUrl');
        $input->SetTrade_type('JSAPI');
        $input->SetScene_info('JSAPI');
        $input->SetOpenid($openid);
        $input->SetTime_start(date("YmdHis"));//订单时间
        $input->SetTime_expire(date("YmdHis",time()+7200));//订单结束时间   2小时有效期
        $wxPayApi=new \WxPayApi();
        $result=$wxPayApi::unifiedOrder($input);

        //存入日志
        $jsApi=new \JsApiPay();
        $jsApi->writeLog(var_export($result,true));

        if($result['return_code']=='SUCCESS' && $result['result_code']=='SUCCESS'){
            //进行重新签名
            $appid=\WxPayConfig::APPID;
            $timeStamp=time();
            $nonceStr=$wxPayApi::getNonceStr();
            $signType='MD5';
            //$sign=$result['sign'];
            $obj=new \WxPayJsApiPay;
            $obj->SetAppid($appid);
            $obj->SetTimeStamp("$timeStamp");
            $obj->SetNonceStr($nonceStr);
            $obj->SetPackage('prepay_id='.$result['prepay_id']);
            $obj->SetSignType($signType);
            $obj->SetSign();

            $sign=$obj->GetSign();
            $package=$obj->GetPackage();
            $timeStamp=$obj->GetTimeStamp();

            //返回jsPay所需数组
            $js_pay_arr=[
                'appId'         => $appid,
                'timeStamp'     => $timeStamp,
                'nonceStr'      => $nonceStr,
                'package'       => $package,
                'signType'      => $signType,
                'paySign'       => $sign,
            ];

            $return=[
                'code' => 1,
                'msg'  => $js_pay_arr,
            ];
            return $return;

        }else{
            $return=[
                'code' => 0,
                'msg'  => '支付失败',
            ];
            return $return;
        }

    }
    /*
     *  微信H5支付
     */
    private function wxH5Pay($order_data){
        $wap_url = get_http_type() . $_SERVER['HTTP_HOST'] ;

        //场景信息  H5支付奇葩信息
        $scene_info="{'h5_info': {'type':'Wap','wap_url': '" . $wap_url ."','wap_name': '夜猫网络'}}";

        $body       = $order_data['goods_name'];                             //商品描述
        $money      = $order_data['pay_money'];                            //支付金额
        $goodId     = $order_data['order_id'];                           //订单编号
        $ip         = get_client_ip(0,true);                   //客户端ip




        $input=new \WxPayUnifiedOrder();                    //调用统一下单类
        $input->SetBody($body);                             //商品标题

        $input->SetOut_trade_no($goodId);                   //订单标号
        $input->SetTotal_fee($money*100);             //金额  按分计算的
        $input->SetSpbill_create_ip($ip);
        $input->SetTime_start(date("YmdHis"));//订单时间
        $input->SetTime_expire(date("YmdHis",time()+7200));     //订单结束时间   2小时有效期
        //$input->SetNotify_url('https://'.$_SERVER['HTTP_HOST']."/api/pay/wx.html");//异步接收微信通知
        $input->SetNotify_url($wap_url.'/api/pay/wxNotifyUrl');   //异步接收微信通知
        $input->SetTrade_type("MWEB");//交易类型


        ////////////////////////////
        $input->SetScene_info($scene_info);//场景信息
        ///////////////////////////
        $wxPayApi=new \WxPayApi();
        $result=$wxPayApi::unifiedOrder($input);

        //存入日志
        $jsApi=new \JsApiPay();
        $jsApi->writeLog(var_export($result,true));

        //换取到微信跳转的中间页

        if($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS'){
            $result_url=urlencode($wap_url ."/mall/order/paySuccess.html");


            $mweb_url=$result['mweb_url']."&redirect_url=".$result_url;
            //$url=$result['mweb_url'];

            echo "<script type='text/javascript'>window.location.href='".$mweb_url."'</script>";
            exit();
            /*$return=[
                'code' => 1,
                'msg'  => $mweb_url
            ];
            return $return;*/
        }else{
            $return=[
                'code' => 0,
                'msg'  => '支付失败',
            ];
            return $return;
        }


    }

    /*
     * 微信退款
     * $out_refund_no  退款单号
     * $order_id       订单编号
     * $money          退款金额
     */
    public function wxRefund($out_refund_no,$order_id,$money){
        //检测单号是否存在  并且未退款


        $input=new \WxPayRefund();
        $input->SetOut_trade_no($order_id);
        $input->SetOut_refund_no($out_refund_no);
        $input->SetTotal_fee($money*100);
        $input->SetRefund_fee($money*100);
        $refund=\WxPayApi::refund($input);
        return $refund;
    }
    /*
     * 支付宝退款
     */
    public function aliPayRefund($out_trade_no,$order_id,$money){
        //检测单号是否存在  并且未退款

        $RequestBuilder = new \AlipayTradeRefundContentBuilder();
        $RequestBuilder->setOutTradeNo($order_id);
        $RequestBuilder->setRefundAmount(number_format($money,2));
        $RequestBuilder->setOutRequestNo($out_trade_no);

        $config = config('alipay_config');
        $Response = new \AlipayTradeService($config);
        $result=$Response->Refund($RequestBuilder);
        $result=json_decode(json_encode($result),true);
        return $result;
    }

    /*
     * 微信退款查询
     */
    public function wxRefundQuery($out_trade_no){
        $input=new \WxPayRefundQuery();
        $input->SetOut_trade_no($out_trade_no);
        $refund=\WxPayApi::refundQuery($input);
        return $refund;
    }
    /*
     * 支付宝退款查询
     */
    public function aliPayRefundQuery($out_trade_no){
        //查询出退款单号
        $refund_order=Db::name('order_refund')->where('order_id',$out_trade_no)->field('order_id,order_refund_id')->find();
        if(is_null($refund_order)){
            return false;
        }

        $RequestBuilder = new \AlipayTradeFastpayRefundQueryContentBuilder();
        $RequestBuilder->setOutTradeNo($out_trade_no);    //商户订单号
        $RequestBuilder->setOutRequestNo($refund_order['order_refund_id']);//退款请求号

        $config = config('alipay_config');
        $Response = new \AlipayTradeService($config);
        $result=$Response->refundQuery($RequestBuilder);
        $result=json_decode(json_encode($result),true);
        return $result;
    }

}